package com.excilys.dao;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.excilys.model.Transaction;
import com.excilys.model.TransactionTransfer;
import com.excilys.utils.Constants;

/**
 * 
 * DAO for transactions
 * 
 * @author excilys dev : YA, SC, VP
 * 
 */
@Repository
public class TransactionDAOHibernateImpl implements ITransactionDAO {

	Logger logger = LoggerFactory.getLogger(TransactionDAOHibernateImpl.class);

	@PersistenceContext
	public EntityManager entityManager;

	@Autowired
	private IAccountDAO myAccountDAO;

	/**
	 * {@inheritDoc}
	 */
	@Override
	public List<Transaction> getAllTransactionsByAccountIdByMonthAndYear(long accountId, DateTime currentDate) {
		Query myQuery = entityManager
				.createQuery("From Transaction where (transactionAccount_accountId = :transactionAccount_accountId OR transferAccount_accountId = :transferAccount_accountId) and MONTH(transactionDate) = :transactionDateMonth AND YEAR(transactionDate) = :transactionDateYear order by transactionDate desc");

		myQuery.setParameter("transactionAccount_accountId", accountId);
		myQuery.setParameter("transferAccount_accountId", accountId);
		myQuery.setParameter("transactionDateMonth", currentDate.getMonthOfYear());
		myQuery.setParameter("transactionDateYear", currentDate.getYear());

		@SuppressWarnings("unchecked")
		List<Transaction> resultTransactionsList = myQuery.getResultList();
		return resultTransactionsList;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public List<Transaction> getAllTransactionsCheckTransferByAccountIdByMonthAndYear(Long accountId, DateTime currentDate) {
		Query myQuery = entityManager
				.createQuery("From Transaction where (transactionAccount_accountId = :transactionAccount_accountId OR transferAccount_accountId = :transferAccount_accountId) and DTYPE != 'TransactionCard'  and MONTH(transactionDate) = :transactionDateMonth AND YEAR(transactionDate) = :transactionDateYear order by transactionDate desc");

		myQuery.setParameter("transactionAccount_accountId", accountId);
		myQuery.setParameter("transferAccount_accountId", accountId);
		myQuery.setParameter("transactionDateMonth", currentDate.getMonthOfYear());
		myQuery.setParameter("transactionDateYear", currentDate.getYear());

		@SuppressWarnings("unchecked")
		List<Transaction> resultTransactionsCardList = myQuery.getResultList();
		return resultTransactionsCardList;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public List<Transaction> getAllTransactionsCardByAccountIdByMonthAndYear(Long accountId, DateTime currentDate) {
		Query myQuery = entityManager
				.createQuery("From Transaction where transactionAccount_accountId = :transactionAccount_accountId and DTYPE = 'TransactionCard' and MONTH(transactionDate) = :transactionDateMonth AND YEAR(transactionDate) = :transactionDateYear order by transactionDate desc");

		myQuery.setParameter("transactionAccount_accountId", accountId);
		myQuery.setParameter("transactionDateMonth", currentDate.getMonthOfYear());
		myQuery.setParameter("transactionDateYear", currentDate.getYear());

		@SuppressWarnings("unchecked")
		List<Transaction> resultTransactionsCardList = myQuery.getResultList();
		return resultTransactionsCardList;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public List<Transaction> getAllTransactionsCheckTransferByAccountIdByMonthAndYear(long accountId, DateTime currentDate, int offset) {

		Query myQuery = entityManager
				.createQuery("From Transaction where DTYPE != 'TransactionCard' AND (transactionAccount_accountId = :transactionAccount_accountId OR transferAccount_accountId = :transferAccount_accountId) AND MONTH(transactionDate) = :transactionDateMonth AND YEAR(transactionDate) = :transactionDateYear order by transactionDate desc");

		myQuery.setParameter("transactionAccount_accountId", accountId);
		myQuery.setParameter("transferAccount_accountId", accountId);
		myQuery.setParameter("transactionDateMonth", currentDate.getMonthOfYear());
		myQuery.setParameter("transactionDateYear", currentDate.getYear());

		myQuery.setFirstResult(offset);
		myQuery.setMaxResults(Constants.MAX_RESULT);

		@SuppressWarnings("unchecked")
		List<Transaction> resultTransactionsList = myQuery.getResultList();
		return resultTransactionsList;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public List<Transaction> getAllTransactionsCardByAccountIdByMonthAndYear(Long accountId, DateTime currentDate, int offset) {
		Query myQuery = entityManager
				.createQuery("From Transaction where transactionAccount_accountId = :transactionAccount_accountId and DTYPE = 'TransactionCard' and MONTH(transactionDate) = :transactionDateMonth AND YEAR(transactionDate) = :transactionDateYear order by transactionDate desc");

		myQuery.setParameter("transactionAccount_accountId", accountId);
		myQuery.setParameter("transactionDateMonth", currentDate.getMonthOfYear());
		myQuery.setParameter("transactionDateYear", currentDate.getYear());

		myQuery.setFirstResult(offset);
		myQuery.setMaxResults(Constants.MAX_RESULT);

		@SuppressWarnings("unchecked")
		List<Transaction> resultTransactionsCardList = myQuery.getResultList();
		return resultTransactionsCardList;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setTransferTransaction(String sourceAccountName, String targetAccountName, double transferAmount) {
		DateTime date = new DateTime();
		TransactionTransfer myTransaction = new TransactionTransfer(transferAmount, date, myAccountDAO.getAccountByName(sourceAccountName),
				myAccountDAO.getAccountByName(targetAccountName));
		entityManager.persist(myTransaction);
	}

}
